home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / bawk.zip / BAWKACT.C < prev    next >
Text File  |  1986-04-15  |  8KB  |  450 lines

  1. /*
  2.  * Bawk C actions compiler
  3.  */
  4. #include <stdio.h>
  5. #include "bawk.h"
  6.  
  7. act_compile( actbuf )
  8. char    *actbuf;    /* where tokenized actions are compiled into */
  9. {
  10.     Where = ACTION;
  11.     return stmt_compile( actbuf );
  12. }
  13.  
  14. pat_compile( actbuf )
  15. char    *actbuf;    /* where tokenized actions are compiled into */
  16. {
  17.     Where = PATTERN;
  18.     return stmt_compile( actbuf );
  19. }
  20.  
  21. stmt_compile( actbuf )
  22. char    *actbuf;    /* where tokenized actions are compiled into */
  23. {
  24.     /*
  25.      * Read and tokenize C actions from current input file into the
  26.      * action buffer.  Strip out comments and whitespace in the
  27.      * process.
  28.      */
  29.     char    *actptr,    /* actbuf pointer */
  30.         *cp,        /* work pointer */
  31.         buf[MAXLINELEN];/* string buffer */
  32.     int    braces,        /* counts '{}' pairs - return when 0 */
  33.         parens,        /* counts '()' pairs */
  34.         i,        /* temp */
  35.         c;        /* current input character */
  36.  
  37.     braces = parens = 0;
  38.     actptr = actbuf;
  39.     while ( (c = getcharacter()) != -1 )
  40.     {
  41.         /*
  42.          * Skip over spaces, tabs and newlines
  43.          */
  44.         if ( c==' ' || c=='\t' || c=='\n' )
  45.             continue;
  46.         if ( c=='#' )
  47.         {
  48.             /*
  49.              * Skip comments.  Comments start with a '#' and
  50.              * end at the next newline.
  51.              */
  52.             while ( (c = getcharacter()) != -1 && c!='\n' )
  53.                 ;
  54.             continue;
  55.         }
  56.  
  57.         if ( c=='{' )
  58.         {
  59.             if ( Where==PATTERN )
  60.             {
  61.                 /*
  62.                  * We're compiling a pattern. The '{' marks
  63.                  * the beginning of an action statement.
  64.                  * Push the character back and return.
  65.                  */
  66.                 ungetcharacter( '{' );
  67.                 break;
  68.             }
  69.             else
  70.             {
  71.                 /*
  72.                  * We must be compiling an action statement.
  73.                  * '{'s mark beginning of action or compound
  74.                  * statements.
  75.                  */
  76.                 ++braces;
  77.                 *actptr++ = T_LBRACE;
  78.             }
  79.         }
  80.         else if ( c=='}' )
  81.         {
  82.             *actptr++ = T_RBRACE;
  83.             if ( ! --braces )
  84.                 /*
  85.                  * Found the end of the action string
  86.                  */
  87.                 break;
  88.         }
  89.         else if ( c=='(' )
  90.         {
  91.             ++parens;
  92.             *actptr++ = T_LPAREN;
  93.         }
  94.         else if ( c==')' )
  95.         {
  96.             if ( --parens < 0 )
  97.                 error( "mismatched '()'", ACT_ERROR );
  98.             *actptr++ = T_RPAREN;
  99.         }
  100.         else if ( c==',' && !braces && !parens && Where==PATTERN )
  101.         {
  102.             /*
  103.              * found a comma outside of any braces or parens-
  104.              * this must be a regular expression seperator.
  105.              */
  106.             ungetcharacter( ',' );
  107.             break;
  108.         }
  109.  
  110.         /*
  111.          * Check if it's a regular expression:
  112.          */
  113.         else if ( c=='/' )
  114.         {
  115.             /*
  116.              * A '/' inside a pattern string starts a regular
  117.              * expression.  Inside action strings, a '/' is
  118.              * the division operator.
  119.              */
  120.             if ( Where == PATTERN )
  121.                 goto dopattern;
  122.             else
  123.                 *actptr++ = T_DIV;
  124.         }
  125.         else if ( c=='@' )
  126.         {
  127. dopattern:
  128.             /*
  129.              * Within action strings, only the '@' may be used to
  130.              * delimit regular expressions
  131.              */
  132.             *actptr++ = T_REGEXP;
  133.             ungetcharacter( c );
  134.             actptr += re_compile( actptr );
  135.         }
  136.  
  137.         /*
  138.          * symbol, string or constant:
  139.          */
  140.         else if ( alpha( c ) )
  141.         {
  142.             /*
  143.              * It's a symbol reference. Copy the symbol into
  144.              * string buffer.
  145.              */
  146.             cp = buf;
  147.             do
  148.                 *cp++ = c;
  149.             while ( (c=getcharacter()) != -1 && alphanum( c ) );
  150.             ungetcharacter( c );
  151.             *cp = 0;
  152.             /*
  153.              * Check if a keyword, builtin function or variable.
  154.              */
  155.             if ( c = iskeyword( buf ) )
  156.                 *actptr++ = c;
  157.             else if ( i = isfunction( buf ) )
  158.             {
  159.                 *actptr++ = T_FUNCTION;
  160.                 storeint( actptr, i );
  161.                 actptr += sizeof( i );
  162.             }
  163.             else
  164.             {
  165.                 /*
  166.                  * It's a symbol name.
  167.                  */
  168.                 *actptr++ = T_VARIABLE;
  169.                 if ( !(cp = findvar( buf )) )
  170.                     cp = addvar( buf );
  171.                 storeptr( actptr, cp );
  172.                 actptr += sizeof( cp );
  173.             }
  174.         }
  175.  
  176.         else if ( c == '"' )
  177.         {
  178.             /*
  179.              * It's a string constant
  180.              */
  181.             *actptr++ = T_STRING;
  182.             actptr = str_compile( actptr, '"' );
  183.         }
  184.         else if ( c == '\'' )
  185.         {
  186.             /*
  187.              * It's a character constant
  188.              */
  189.             *actptr++ = T_CONSTANT;
  190.             str_compile( buf, '\'' );
  191.             storeint( actptr, *buf );
  192.             actptr += sizeof( i );
  193.         }
  194.  
  195.         else if ( num( c ) )
  196.         {
  197.             /*
  198.              * It's a numeric constant
  199.              */
  200.             *actptr++ = T_CONSTANT;
  201.             cp = buf;
  202.             do
  203.                 *cp++ = c;
  204.             while ( (c=getcharacter()) != -1 && num(c) );
  205.             ungetcharacter( c );
  206.             *cp = 0;
  207.             storeint( actptr, atoi( buf ) );
  208.             actptr += sizeof( i );
  209.         }
  210.  
  211.         /*
  212.          * unary operator:
  213.          */
  214.         else if ( c == '$' )
  215.             *actptr++ = T_DOLLAR;
  216.  
  217.         /*
  218.          * or binary operator:
  219.          */
  220.         else if ( c == '=' )
  221.         {
  222.             if ( (c=getcharacter()) == '=' )
  223.                 *actptr++ = T_EQ;
  224.             else
  225.             {
  226.                 ungetcharacter( c );
  227.                 *actptr++ = T_ASSIGN;
  228.             }
  229.         }
  230.  
  231.         else if ( c == '!' )
  232.         {
  233.             if ( (c=getcharacter()) == '=' )
  234.                 *actptr++ = T_NE;
  235.             else
  236.             {
  237.                 ungetcharacter( c );
  238.                 *actptr++ = T_LNOT;
  239.             }
  240.         }
  241.  
  242.         else if ( c == '<' )
  243.         {
  244.             if ( (c=getcharacter()) == '<' )
  245.                 *actptr++ = T_SHL;
  246.             else if ( c == '=' )
  247.                 *actptr++ = T_LE;
  248.             else
  249.             {
  250.                 ungetcharacter( c );
  251.                 *actptr++ = T_LT;
  252.             }
  253.         }
  254.  
  255.         else if ( c == '>' )
  256.         {
  257.             if ( (c=getcharacter()) == '>' )
  258.                 *actptr++ = T_SHR;
  259.             else if ( c == '=' )
  260.                 *actptr++ = T_GE;
  261.             else
  262.             {
  263.                 ungetcharacter( c );
  264.                 *actptr++ = T_GT;
  265.             }
  266.         }
  267.  
  268.         else if ( c == '&' )
  269.         {
  270.             if ( (c=getcharacter()) == '&' )
  271.                 *actptr++ = T_LAND;
  272.             else
  273.             {
  274.                 ungetcharacter( c );
  275.                 *actptr++ = T_AND;
  276.             }
  277.         }
  278.  
  279.         else if ( c == '|' )
  280.         {
  281.             if ( (c=getcharacter()) == '|' )
  282.                 *actptr++ = T_LIOR;
  283.             else
  284.             {
  285.                 ungetcharacter( c );
  286.                 *actptr++ = T_IOR;
  287.             }
  288.         }
  289.         else if ( c == '+' )
  290.         {
  291.             if ( (c=getcharacter()) == '+' )
  292.                 *actptr++ = T_INCR;
  293.             else
  294.             {
  295.                 ungetcharacter( c );
  296.                 *actptr++ = T_ADD;
  297.             }
  298.         }
  299.  
  300.         else if ( c == '-' )
  301.         {
  302.             if ( (c=getcharacter()) == '-' )
  303.                 *actptr++ = T_DECR;
  304.             else
  305.             {
  306.                 ungetcharacter( c );
  307.                 *actptr++ = T_SUB;
  308.             }
  309.         }
  310.  
  311.         /*
  312.          * punctuation
  313.          */
  314.         else if ( instr( c, "[](),;*/%+-^~" ) )
  315.             *actptr++ = c;
  316.  
  317.         else
  318.         {
  319.             /*
  320.              * Bad character in input line
  321.              */
  322.             error( "lexical error", ACT_ERROR );
  323.         }
  324.  
  325.         if ( actptr >= Workbuf + MAXWORKBUFLEN )
  326.             error( "action too long", MEM_ERROR );
  327.     }
  328.     if ( braces || parens )
  329.         error( "mismatched '{}' or '()'", ACT_ERROR );
  330.  
  331.     *actptr++ = T_EOF;
  332.  
  333.     return actptr - actbuf;
  334. }
  335.  
  336. str_compile( str, delim )
  337. char *str, delim;
  338. {
  339.     /*
  340.      * Compile a string from current input file into the given string
  341.      * buffer.  Stop when input character is the delimiter in "delim".
  342.      * Returns a pointer to the first character after the string.
  343.      */
  344.     int c;
  345.     char buf[ MAXLINELEN ];
  346.  
  347.     while ( (c = getcharacter()) != -1 && c != delim)
  348.     {
  349.         if ( c  == '\\' )
  350.         {
  351.             switch ( c = getcharacter() )
  352.             {
  353.             case -1: goto err;
  354.             case 'b': c = '\b'; break;
  355.             case 'n': c = '\n'; break;
  356.             case 't': c = '\t'; break;
  357.             case 'f': c = '\f'; break;
  358.             case 'r': c = '\r'; break;
  359.             case '0':
  360.             case '1':
  361.             case '2':
  362.             case '3':
  363.                 *buf = c;
  364.                 for ( c=1; c<3; ++c )
  365.                 {
  366.                     if ( (buf[c]=getcharacter()) == -1 )
  367.                         goto err;
  368.                 }
  369.                 buf[c] = 0;
  370.                 sscanf( buf, "%o", &c );
  371.                 break;
  372.             case '\n':
  373.                 if ( getcharacter() == -1 )
  374.                     goto err;
  375.             default:
  376.                 if ( (c = getcharacter()) == -1 )
  377.                     goto err;
  378.             }
  379.         }
  380.         *str++ = c;
  381.     }
  382.     *str++ = 0;
  383.  
  384.     return str;
  385. err:
  386.     sprintf( buf, "missing %c delimiter", delim );
  387.     error( buf, 4 );
  388. }
  389.  
  390. storeint( ip, i )
  391. int *ip, i;
  392. {
  393.     return *ip = i;
  394. }
  395.  
  396. storeptr( pp, p )
  397. char **pp, *p;
  398. {
  399.     return *pp = p;
  400. }
  401.  
  402. fetchint( ip )
  403. int *ip;
  404. {
  405.     return *ip;
  406. }
  407.  
  408. char *
  409. fetchptr( pp )
  410. char **pp;
  411. {
  412.     return *pp;
  413. }
  414.  
  415. getoken()
  416. {
  417.     char *cp;
  418.     int i;
  419.  
  420.     switch ( Token = *Actptr++ )
  421.     {
  422.     case T_STRING:
  423.     case T_REGEXP:
  424.         Value.dptr = Actptr;
  425.         Actptr += strlen( Actptr ) + 1;
  426.         break;
  427.     case T_VARIABLE:
  428.         Value.dptr = fetchptr( Actptr );
  429.         Actptr += sizeof( cp );
  430.         break;
  431.     case T_FUNCTION:
  432.     case T_CONSTANT:
  433.         Value.ival = fetchint( Actptr );
  434.         Actptr += sizeof( i );
  435.         break;
  436.     case T_EOF:
  437.         --Actptr;
  438.     default:
  439.         Value.dptr = 0;
  440.     }
  441.  
  442. #ifdef DEBUG
  443.     if ( Debug > 1 )
  444.         printf( "Token='%c' (0x%x), Value=%d\n",
  445.             Token,Token,Value.ival );
  446. #endif
  447.  
  448.     return Token;
  449. }
  450.